package com.googlecode.chigs.web.config.module;

import com.googlecode.chigs.domain.ConfigRevision;
import com.googlecode.chigs.domain.Module;
import com.googlecode.chigs.domain.Product;
import com.googlecode.chigs.domain.Revision;
import com.googlecode.chigs.repository.ChigsFacade;
import com.googlecode.chigscommons.web.common.modal.AModalManagement;
import com.googlecode.chigscommons.web.common.table.AjaxFallbackDefaultDataTableBuilder;
import com.googlecode.chigscommons.web.util.ComponentUtil;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.extensions.wizard.WizardStep;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class EditOrCreateModuleStep extends WizardStep {
	private static final Logger log = LoggerFactory.getLogger(EditOrCreateModuleStep.class);
	
	@SpringBean
	private ChigsFacade chigs;

	private final ConfigRevision configRevision;

    private Module module;

	private AModalManagement<Revision> revisonManagement;

	private final List<Module> modules;

	private final DropDownChoice<Module> moduleSelector;
	
	public EditOrCreateModuleStep(ConfigRevision configRevision, Product product, boolean editable) {
		this.configRevision = configRevision;

		modules = chigs.loadModulesByProduct(product);
		
		moduleSelector = getModuleSelector();
		moduleSelector.setVisible(editable);
		add(moduleSelector);
		getRevisonManagement().setEditMode(false);
		getRevisonManagement().setDelete(editable);
		add(getRevisonManagement().getPresenter());
	}

	private DropDownChoice<Module> getModuleSelector() {
		final List<Module> available = new ArrayList<Module>(modules);
		
		for (Revision revision : configRevision.getRevisions()) {
			available.remove(revision.getModule());
		}
		
		DropDownChoice<Module> dropDownChoice = new DropDownChoice<Module>("module",
				new PropertyModel<Module>(EditOrCreateModuleStep.this, "module"),
				available,
				new ChoiceRenderer<Module>("name", "id")) {
		};
		dropDownChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
			@Override
			protected void onUpdate(AjaxRequestTarget target) {
				addModule(available, module);
				module = null;
                Component fp = ComponentUtil.getComponentByClass(getPage(), FeedbackPanel.class);
                if (fp != null) {
                	target.addComponent(fp);
                }
				target.addComponent(moduleSelector);
				target.addComponent(getRevisonManagement().getPresenter());
			}

			private void addModule(final List<Module> available, Module mod) {
				Revision revision = chigs.loadLatestRevision(mod);
				revision.setConfigPairs(chigs.loadConfigPairsByRevision(revision));
				configRevision.getRevisions().add(revision);
				available.remove(mod);
				for (Module dependency : revision.getDependencies()) {
					for (Module avail : new ArrayList<Module>(available)) {
						if (dependency.getId().longValue() == avail.getId().longValue()) {
							info("added dependency " + dependency.getName());
							addModule(available, avail);
						}
					}
				}
			}
		});
		dropDownChoice.setOutputMarkupId(true);
		return dropDownChoice;
	}

	private AModalManagement<Revision> getRevisonManagement() {
		if (revisonManagement == null) {
			revisonManagement = new AModalManagement<Revision>("revisionPresenter", "revisionEditor", "revisionCreate") {
				@Override
				protected List<Revision> getValues() {					
					return configRevision.getRevisions();
				}

				@Override
				public Revision getNewObject() {
					return new Revision();
				}

				@Override
				protected MarkupContainer getPresenterParent() {
					return EditOrCreateModuleStep.this;
				}

				@Override
				protected MarkupContainer getEditorParent() {
					return EditOrCreateModuleStep.this;
				}

				@Override
				protected Component fillForm(String id, IModel<Revision> model) {
					return null;
				}

				@Override
				protected void addColumns(AjaxFallbackDefaultDataTableBuilder builder) {
					builder.addPropertyColumn("module.name", false)
					.addPropertyColumn("nr", false)
					.setNumberOfRows(10);
				}

				@Override
				protected void removeDone(AjaxRequestTarget target, Revision object) {
					final DropDownChoice<Module> ms = getModuleSelector();
					EditOrCreateModuleStep.this.addOrReplace(ms);
					target.addComponent(ms);
				}

				@Override
				protected void notifyValueChanged(Revision currentObject) {
					super.notifyValueChanged(currentObject);
					if (log.isDebugEnabled()) {
						log.debug("Revisions in config revision object:");
						for (Revision a : configRevision.getRevisions()) {
							log.debug(a.toString());	
						}
					}
				}

				@Override
				protected void notifyValueToAdd(Revision currentObject) {
					super.notifyValueToAdd(currentObject);
					if (log.isDebugEnabled()) {
						log.debug("Revisions in config revision object:");
						for (Revision a : configRevision.getRevisions()) {
							log.debug(a.toString());	
						}
					}
				}
			};
		}
		return revisonManagement;
	}
}
